/**********************************************************************************
// Bitmap Source
//
// Creation:	12 Jun 2007
// Updated:		27 Set 2009
// Compiler:	Visual Studio 2008
//
// Comments:	Work with bitmap images
//
**********************************************************************************/

#include "Bitmap.h"

/**********************************************************************************/

Bitmap::Bitmap(char *fileName)
{
	imgData = NULL;
	Load(fileName);
}


/**********************************************************************************/

Bitmap::Bitmap()
{
	imgData = NULL;
}

/**********************************************************************************/

Bitmap::~Bitmap()
{
	// the destructor releases all memory associated with the bitmap
	if (imgData)
	{
		// release memory
		delete [] imgData;
		imgData = NULL;
	}
}

/**********************************************************************************/

int Bitmap::Load(char *fileName)
{

	HANDLE  fileHandle;	// the file handle
	DWORD	nBytesRead;	// number of bytes read from ReadFile operation
	int		readResult;	// result of ReadFile operation

	// open the file if it exists
	if ((fileHandle = CreateFile(fileName, 
							     FILE_READ_DATA, 
								 FILE_SHARE_READ, 
								 NULL,
								 OPEN_ALWAYS,
								 FILE_ATTRIBUTE_NORMAL,
								 NULL)) == INVALID_HANDLE_VALUE)
		// file opening failure
		return NULL; 

	// now load the bitmap file header
	readResult = ReadFile(fileHandle, 
		                  &bitmapHeader, 
			              sizeof(BITMAPFILEHEADER), 
			              &nBytesRead,
			              NULL);

	if (!readResult || (nBytesRead == 0))
		// problems reading the file
		return NULL; 

	// test if this is a bitmap file
	if (bitmapHeader.bfType != BITMAP_ID)
	{	
		// close the file
		CloseHandle(fileHandle);
		// return error, file is not a bitmap
		return NULL; 
	}

	// now we know this is a bitmap, so read in all the sections

	// first the bitmap infoheader
	readResult = ReadFile(fileHandle, 
			              &bitmapInfo, 
						  sizeof(BITMAPINFOHEADER), 
						  &nBytesRead,
						  NULL);
	
	if (!readResult || (nBytesRead == 0))
		// problems reading the file
		return NULL; 

	// load the image data itself
	if (bitmapInfo.biBitCount==8 || 
		bitmapInfo.biBitCount==16 || 
	    bitmapInfo.biBitCount==24)
	{
		// allocate the memory for the image
		if (!(imgData = new UCHAR[bitmapInfo.biSizeImage]))
		{
			// close the file
			CloseHandle(fileHandle);

			// return error, memory allocation failure
			return NULL;
		}
		
		// now read it in
		readResult = ReadFile(fileHandle, 
		                      imgData, 
							  bitmapInfo.biSizeImage, 
							  &nBytesRead,
							  NULL);
		if (!readResult || (nBytesRead == 0))
			// problems reading the file
			return NULL;
	} 
	else
	{
		// serious problem, bitmap BPP is unknown
		return NULL;

	} 

	// close the file
	CloseHandle(fileHandle);

	// if bitmap is bottom-up, flip it
	if (bitmapInfo.biHeight > 0) 
	{
		// flip the bitmap
		FlipBitmap(imgData, 
			       bitmapInfo.biWidth * (bitmapInfo.biBitCount/8), 
				   bitmapInfo.biHeight);
	}

	// return success
	return 1;
}


/**********************************************************************************/

int Bitmap::FlipBitmap(UCHAR *image, int bytesPerLine, int height)
{
	// this function is used to flip bottom-up .BMP images

	UCHAR * buffer; // used to perform the image processing

	// allocate the temporary buffer
	if (!(buffer = new UCHAR[bytesPerLine * height]))
		return 0;

	// copy image to work area
	memcpy(buffer, image, bytesPerLine * height);

	// flip vertically
	for (int i=0; i < height; i++)
		memcpy(&image[((height-1) - i) * bytesPerLine], 
		       &buffer[i * bytesPerLine], 
			   bytesPerLine);

	// release the memory
	delete [] buffer;

	// return success
	return 1;
}

/**********************************************************************************/